module idf
(
    input   wire                clk,
    input   wire    [31:00]     idf_instr_i,
    //  bypass
    input   wire    [04:00]     idf_gpr_ids_rd_i,
    input   wire    [04:00]     idf_gpr_ex_rd_i,
    input   wire    [04:00]     idf_gpr_mem_rd_i,
    input   wire    [04:00]     idf_gpr_wb_rd_i,
    input   wire    [11:00]     idf_csr_ids_rd_i,
    input   wire    [11:00]     idf_csr_ex_rd_i,
    input   wire    [11:00]     idf_csr_mem_rd_i,
    input   wire    [11:00]     idf_csr_wb_rd_i,

    //  gpr write back
    input   wire                idf_gpr_write_back_en_i,
    input   wire    [04:00]     idf_gpr_write_back_id_i,
    input   wire    [63:00]     idf_gpr_write_back_data_i,
    //  type
    output  wire                idf_instr_load_o,     
    output  wire                idf_instr_load_fp_o,  
    output  wire                idf_instr_misc_mem_o, 
    output  wire                idf_instr_op_imm_o   ,
    output  wire                idf_instr_auipc_o    ,
    output  wire                idf_instr_op_imm_32_o,
    output  wire                idf_instr_store_o    ,
    output  wire                idf_instr_store_fp_o ,
    output  wire                idf_instr_amo_o   ,   
    output  wire                idf_instr_op_o   ,    
    output  wire                idf_instr_lui_o  ,    
    output  wire                idf_instr_op_32_o ,   
    output  wire                idf_instr_madd_o,     
    output  wire                idf_instr_msub_o,     
    output  wire                idf_instr_nmsub_o,    
    output  wire                idf_instr_nmadd_o,    
    output  wire                idf_instr_op_fp_o,    
    output  wire                idf_instr_branch_o ,  
    output  wire                idf_instr_jalr_o  ,   
    output  wire                idf_instr_jal_o    ,  
    output  wire                idf_instr_system_o ,  
    //
    output  wire    [02:00]     idf_funct3_o        ,
    output  wire    [06:00]     idf_funct7_o        ,
    output  wire    [04:00]     idf_funct5_o        ,
    output  wire    [11:00]     idf_funct12_o       ,
    output  wire    [10:00]     idf_alu_op_o        ,
    output  wire    [08:00]     idf_mdu_op_o        ,
    output  wire    [01:00]     idf_alu_shift_mode_o,
    output  wire    [03:00]     idf_disp_target_o   ,
    //
    output  wire                idf_operand1_sel_o,
    output  wire                idf_operand2_sel_o,
    output  wire                idf_rs1_bypassdata_sel_o     ,
    output  wire                idf_rs2_bypassdata_sel_o     ,
    output  wire                idf_csr_bypassdata_sel_o     ,
    output  wire                idf_rs1_bypassdata_ex_sel_o  ,
    output  wire                idf_rs1_bypassdata_mem_sel_o ,
    output  wire                idf_rs1_bypassdata_wb_sel_o  ,
    output  wire                idf_rs2_bypassdata_ex_sel_o  ,
    output  wire                idf_rs2_bypassdata_mem_sel_o ,
    output  wire                idf_rs2_bypassdata_wb_sel_o  ,
    output  wire                idf_csr_bypassdata_ex_sel_o  ,
    output  wire                idf_csr_bypassdata_mem_sel_o ,
    output  wire                idf_csr_bypassdata_wb_sel_o  ,
    //
    output  wire                idf_data_raw_depcy_o,
    //

    output  wire                idf_gpr_write_back_en_o      ,
    output  wire    [04:00]     idf_gpr_write_back_id_o      ,
    output  wire                idf_gpr_write_back_from_alu_o,
    output  wire                idf_gpr_write_back_from_lsu_o,
    output  wire                idf_gpr_write_back_from_mdu_o,
    //
    output  wire    [11:00]     idf_csr_id_o                 ,
	//
    output  wire                idf_csr_write_back_en_o      ,
    output  wire    [11:00]     idf_csr_write_back_id_o      ,
    output  wire    [63:00]     idf_imm_o,
    output  wire    [63:00]     idf_jalr_offset_o            ,
    output  wire                idf_illegal_instr_flag_o,
    //
    output  wire    [63:00]     idf_gpr_output1_o,
    output  wire    [63:00]     idf_gpr_output2_o
);
//
    //
    wire    [04:00]     dec_gpr_id1_o; 				  
	wire    [04:00]     dec_gpr_id2_o;

// ------------------------------------------------------------------------------------------------------
    decoder                                                 decoder
    (   
        .instr                                              (idf_instr_i          ),
        .instr_load                                         (idf_instr_load_o     ),
        .instr_load_fp                                      (idf_instr_load_fp_o  ),
        .instr_misc_mem                                     (idf_instr_misc_mem_o ),
        .instr_op_imm                                       (idf_instr_op_imm_o   ),
        .instr_auipc                                        (idf_instr_auipc_o    ),
        .instr_op_imm_32                                    (idf_instr_op_imm_32_o),
        .instr_store                                        (idf_instr_store_o    ),
        .instr_store_fp                                     (idf_instr_store_fp_o ),
        .instr_amo                                          (idf_instr_amo_o      ),
        .instr_op                                           (idf_instr_op_o       ),
        .instr_lui                                          (idf_instr_lui_o      ),
        .instr_op_32                                        (idf_instr_op_32_o    ),
        .instr_madd                                         (idf_instr_madd_o     ),
        .instr_msub                                         (idf_instr_msub_o     ),
        .instr_nmsub                                        (idf_instr_nmsub_o    ),
        .instr_nmadd                                        (idf_instr_nmadd_o    ),
        .instr_op_fp                                        (idf_instr_op_fp_o    ),
        .instr_branch                                       (idf_instr_branch_o   ),
        .instr_jalr                                         (idf_instr_jalr_o     ),
        .instr_jal                                          (idf_instr_jal_o      ),
        .instr_system                                       (idf_instr_system_o   ),                 
        .funct3                                             (idf_funct3_o                 ),
        .funct7                                             (idf_funct7_o                 ),
        .funct5                                             (idf_funct5_o                 ),
        .funct12                                            (idf_funct12_o                ),
        .alu_op                                             (idf_alu_op_o                 ),                         
        .mdu_op                                             (idf_mdu_op_o                 ),
        .alu_shift_mode                                     (idf_alu_shift_mode_o         ),                 
        .disp_target                                        (idf_disp_target_o            ),                    
        .gpr_id1                                            (dec_gpr_id1_o               ),
        .gpr_id2                                            (dec_gpr_id2_o               ),
        .operand1_sel                                       (idf_operand1_sel_o          ),
        .operand2_sel                                       (idf_operand2_sel_o          ),
        .gpr_write_back_en                                  (idf_gpr_write_back_en_o      ),              
        .gpr_write_back_id                                  (idf_gpr_write_back_id_o      ),
        .gpr_write_back_from_alu                            (idf_gpr_write_back_from_alu_o),      
        .gpr_write_back_from_lsu                            (idf_gpr_write_back_from_lsu_o),
        .gpr_write_back_from_mdu                            (idf_gpr_write_back_from_mdu_o),
        .csr_id                                             (idf_csr_id_o                 ),
        .csr_write_back_en                                  (idf_csr_write_back_en_o      ),
        .csr_write_back_id                                  (idf_csr_write_back_id_o      ),
        .imm                                                (idf_imm_o                    ),
        .jalr_offset                                        (idf_jalr_offset_o            ),
        .illegal_instr_flag                                 (idf_illegal_instr_flag_o     )
    );

    //  gpr-----------------------------------------------------------------------------------------------------
    gprs                                                    gprs
    (
     	.clk												(clk), 
	    .gpr_write_back_en                                  (idf_gpr_write_back_en_i  ),      
	    .gpr_write_back_data                                (idf_gpr_write_back_data_i),    
	    .gpr_write_back_id                                  (idf_gpr_write_back_id_i  ),		   	
	    .gpr_id1                                            (dec_gpr_id1_o            ), 				  
	    .gpr_id2                                            (dec_gpr_id2_o            ), 				   
	    .gpr_output1                                        (idf_gpr_output1_o        ),	      		
		.gpr_output2                                        (idf_gpr_output2_o        )
	);
    
    // -----------------------------------------------gpr数据相关-----------------------------------------
    //  gpr
    //  处理单周期指令的、可用数据旁路解决的数据相关
    //  由于ID之后还有ex、mem、WB三级流水线
    //  故需要定义三个寄存器，记录当前各流水段上指令的gpr_write_back_id。

    //  判断数据相关是否可以通过旁路解决
    assign  idf_data_raw_depcy_o                =       (dec_gpr_id1_o !=  5'b0     & dec_gpr_id1_o ==  idf_gpr_ids_rd_i)   |
                                                        (dec_gpr_id2_o !=  5'b0     & dec_gpr_id2_o ==  idf_gpr_ids_rd_i)   |
                                                        (idf_csr_id_o  !=  12'b0    & idf_csr_id_o  ==  idf_csr_ids_rd_i)   ;
    //  判断rs1的旁路数据来源                   
    assign  idf_rs1_bypassdata_ex_sel_o         =       dec_gpr_id1_o ==  idf_gpr_ex_rd_i   ;
    assign  idf_rs1_bypassdata_mem_sel_o        =       dec_gpr_id1_o ==  idf_gpr_mem_rd_i  ;
    assign  idf_rs1_bypassdata_wb_sel_o         =       dec_gpr_id1_o ==  idf_gpr_wb_rd_i   ;

    //  判断rs2的旁路数据来源
    assign  idf_rs2_bypassdata_ex_sel_o         =       dec_gpr_id2_o ==  idf_gpr_ex_rd_i   ;
    assign  idf_rs2_bypassdata_mem_sel_o        =       dec_gpr_id2_o ==  idf_gpr_mem_rd_i  ;
    assign  idf_rs2_bypassdata_wb_sel_o         =       dec_gpr_id2_o ==  idf_gpr_wb_rd_i   ; 
    //  判断rs1、rs2是否使用旁路数据
    assign  idf_rs1_bypassdata_sel_o            =       dec_gpr_id1_o !=  5'b0            &
                                                    (   idf_rs1_bypassdata_ex_sel_o       ||
                                                        idf_rs1_bypassdata_mem_sel_o      ||
                                                        idf_rs1_bypassdata_wb_sel_o       );
    assign  idf_rs2_bypassdata_sel_o            =       dec_gpr_id2_o !=  5'b0            &
                                                    (   idf_rs2_bypassdata_ex_sel_o       ||
                                                        idf_rs2_bypassdata_mem_sel_o      ||
                                                        idf_rs2_bypassdata_wb_sel_o       );
// --------------------------------------------------------------------------------------------------------------
// -----------------------------------------------csr数据相关-----------------------------------------   
    //  判断csr的旁路数据来源
    assign  idf_csr_bypassdata_ex_sel_o         =       idf_csr_id_o   ==  idf_csr_ex_rd_i  ;
    assign  idf_csr_bypassdata_mem_sel_o        =       idf_csr_id_o   ==  idf_csr_mem_rd_i ;
    assign  idf_csr_bypassdata_wb_sel_o         =       idf_csr_id_o   ==  idf_csr_wb_rd_i  ;
    //  判断csr是否使用旁路数据
    assign  idf_csr_bypassdata_sel_o            =       idf_csr_id_o  !=  12'b0       &&
                                                    (   idf_csr_bypassdata_ex_sel_o   ||
                                                        idf_csr_bypassdata_mem_sel_o  ||
                                                        idf_csr_bypassdata_wb_sel_o   );
endmodule    
   